package servlet;

import it.polimi.swimv2.exception.AbilityExistsException;
import it.polimi.swimv2.exception.ModifyException;
import it.polimi.swimv2.remote.AbilityManagerRemote;
import it.polimi.swimv2.util.RemoteBindingName;

import java.io.IOException;
import java.util.Collection;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * Servlet implementation class AdminAbilityServlet
 */
public class AdminAbilityServlet extends HttpServlet {
	
	

	
	// Page references:
	private static final String ADMIN_ABILITIES_JSP = "adminAbilities.jsp";
	private static final String ERROR_JSP = "error.jsp";
	private static final String INDEX_JSP = "index.jsp";
	//Action performed by this Servlet:
	private static final String SHOW_ADMIN_ABILITIES_ACT = "showAdminAbilities";
	private static final String ADD_DECLARABLE_ABILITY_ACT = "addDeclarableAbility";
	private static final String REMOVE_DECLARABLE_ABILITY_ACT = "removeDeclarableAbility";
	// Parameters in HttpRequest:
	private static final String ABILITY_NAME_REQPARAM = "abilityName";//String
	private static final String DECLARABLE_ABILITIES_REQPARAM = "declarableAbilities";//Collection<String>
	private static final String ERROR_REQPARAM = "error";//String
	//ERROR Values:
	private static final String ABILITY_EXISTS_ERRVALUE = "abilityAlreadyExists";
	private static final String NOT_VALID_ABILITY_ERRORVALUE = "notValidAbility";
	private static final String NO_ERROR_ERRORVALUE ="noError";
	private static final long serialVersionUID = 1L;
	private static final String ACT_PARAMETER = "act";
	private static final String SESSION_ADMIN = "admin";

	/**
	 * @see HttpServlet#HttpServlet()
	 */
	public AdminAbilityServlet() {
		super();
	}

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		chooseAction(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {

		chooseAction(request, response);
	}

	private void chooseAction(HttpServletRequest request,
			HttpServletResponse response) throws IOException, ServletException {
		HttpSession session = request.getSession();
		String username = (String) session.getAttribute(SESSION_ADMIN);
		String actParam = request.getParameter(ACT_PARAMETER);
		if (username == null||actParam==null) {
			response.sendRedirect(INDEX_JSP);
			return;
		}
		if (actParam.equals(SHOW_ADMIN_ABILITIES_ACT)) {
			showAdminAbilities(request, response);
		} else if (actParam.equals(ADD_DECLARABLE_ABILITY_ACT)) {
			processAddDeclarableAbility(request, response);
		} else if (actParam.equals(REMOVE_DECLARABLE_ABILITY_ACT)) {
			processRemoveDeclarableAbility(request, response);
		} else {
			response.sendRedirect(INDEX_JSP);
		}

	}

	private void showAdminAbilities(HttpServletRequest request,
			HttpServletResponse response) throws IOException, ServletException {
		try {
			AbilityManagerRemote rem = retrieveAbilityManagerRemote();
			Collection<String> declarableAbilities = rem.getDeclarableAbilities();
			request.setAttribute(DECLARABLE_ABILITIES_REQPARAM,	declarableAbilities);
			RequestDispatcher dispatcher = request.getRequestDispatcher(ADMIN_ABILITIES_JSP);
			dispatcher.forward(request, response);
		} catch (NamingException e) {
			response.sendRedirect(ERROR_JSP);
		}
	}

	private void processAddDeclarableAbility(HttpServletRequest request,
			HttpServletResponse response) throws IOException, ServletException {
		
		try {
			AbilityManagerRemote rem=retrieveAbilityManagerRemote();
			String abilityName=request.getParameter(ABILITY_NAME_REQPARAM);
			if(abilityName==null){
				response.sendRedirect(INDEX_JSP);
				return;
			}else{
				rem.createNewDeclarableAbility(abilityName);
				request.setAttribute(ERROR_REQPARAM, NO_ERROR_ERRORVALUE);
				showAdminAbilities(request, response);
			}
		} catch (NamingException e) {
			response.sendRedirect(ERROR_JSP);
		}catch (ModifyException e){
			request.setAttribute(ERROR_REQPARAM, NOT_VALID_ABILITY_ERRORVALUE);
			showAdminAbilities(request, response);
		}catch(AbilityExistsException e){
			request.setAttribute(ERROR_REQPARAM, ABILITY_EXISTS_ERRVALUE);
			showAdminAbilities(request, response);
		}

	}

	private void processRemoveDeclarableAbility(HttpServletRequest request,
			HttpServletResponse response) throws IOException, ServletException {
		try {
			AbilityManagerRemote rem=retrieveAbilityManagerRemote();
			String abilityName=request.getParameter(ABILITY_NAME_REQPARAM);
			if(abilityName==null){
				response.sendRedirect(INDEX_JSP);
				return;
			}else{
				rem.deleteDeclarableAbility(abilityName);
				showAdminAbilities(request, response);
			}
		} catch (NamingException e) {
			response.sendRedirect(ERROR_JSP);
		}

	}

	

	private AbilityManagerRemote retrieveAbilityManagerRemote()
			throws NamingException {
		Context jndiContext = new InitialContext();
		Object ref = jndiContext.lookup(RemoteBindingName.ABILITY_MANAGER);
		AbilityManagerRemote rem = (AbilityManagerRemote) ref;
		return rem;
	}
}
